/**
 * Widget 控件与 RawField 原始控件数据转换
 */
import Widget from './Widget'
import { LocateType, RawField, WidgetData, WidgetKind } from '@/types'
import { createId } from '@/utils'
import { getWidgetOption } from './option'

/**
 *  根据后端记录的 JSON 原始控件数据创建控件
 * @param {RawField} raw 后端记录的原始控件数据
 * @param {WidgetData} extra 额外的控件数据
 * @returns {Widget} 控件
 */
export function createRawWidget(
  /** 后端记录的原始控件数据 */
  raw: RawField,
  /** 额外的控件数据 */
  extra?: Partial<WidgetData>
) {
  let {
    id,
    type,
    signStyle,
    widgetName: name,
    p = 0,
    w,
    h,
    x,
    y,
    crossPageSeal,
    applyPage,
    batch,
    linkId,
    isRequired: required = true,
    widgetValue: value,
    widgetSource: source,
    locateType
  } = raw

  /** 定位坐标 */
  const position = locateType === LocateType.LEFT_TOP ? { x, y } : { ox: x, oy: y }

  type = type ?? signStyle

  let widgetData: WidgetData = {
    id,
    type,
    kind: (batch && WidgetKind.BATCH) || (crossPageSeal && WidgetKind.RIDING) || undefined,
    name,
    p,
    w,
    h,
    applyPage,
    linkId,
    required: !!required,
    value,
    source,
    ...position,
    ...extra
  }

  const option = getWidgetOption(type)

  widgetData = option.rawWidgetCreator?.(widgetData, raw) || widgetData

  return new Widget(widgetData)
}

/**
 * 生成原始控件数据（提供给后端）
 * @param {Widget} widget
 * @return {RawField}
 */
export function getRawField(widget: Widget) {
  const {
    id,
    type,
    name: widgetName,
    actor: { name },
    p,
    w,
    h,
    ox: x,
    oy: y,
    isRiding,
    isBatch,
    applyPage,
    linkId,
    required: isRequired,
    value: widgetValue,
    source: widgetSource
  } = widget

  const data = {
    id,
    type,
    signStyle: type,
    label: widget.option.name,
    name,
    widgetName,
    p,
    w: Math.floor(w),
    h: Math.floor(h),
    x: Math.floor(x),
    y: Math.floor(y),
    crossPageSeal: isRiding ? 1 : undefined,
    batch: isBatch || undefined,
    applyPage: applyPage || undefined,
    linkId: linkId || undefined,
    isRequired,
    widgetValue,
    widgetSource
  } as RawField

  return widget.option.rawFieldGetter?.(widget, data) || data
}

/**
 * 生成批量控件的原始数据，将单个批量控件按页码生成多份（提供给后端）
 * @param {Widget} widget
 * @return {RawField[]}
 */
export function getBatchField(widget: Widget): RawField[] {
  if (!widget.isBatch) return []

  const id = widget.id
  const raw = widget.getRawField()

  return widget.pages.map(
    (p, index) =>
      ({
        ...raw,

        p,

        /** 首个控件沿用 id */
        id: index ? createId() : id,

        /** 为非首个控件标记 `batchId` 便于后期删除 */
        batchId: index ? id : undefined
      } as RawField)
  )
}
